package bioinspired.routing.routingTable;	
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.GraphPath;
import org.jgrapht.ListenableGraph;
import org.jgrapht.alg.KShortestPaths;

/**
 * This class is used to built the routing tables with the k-shortest path
 * algorithm. The algorithm used could be found in 
 * http://jgrapht.org/javadoc/org/jgrapht/alg/KShortestPaths.html
* @author YEISON JULIAN CAMARGO BARAJAS
*/
public class RoutingTable {

   /*
    * Constructor
    */
	/**
	 * The constructor of the RoutingTable class. It receives the graph
	 * from the GraphCreator class and performs the k-shortest algorithm.
	 * @param graph
	 * The graph containing the vertices and edges.
	 */
   public RoutingTable(org.jgrapht.Graph graph) {
       g = graph;
   }
   /*
    * Getters
    */
   
   /**
    * Retrieve the routing table formed after the k-shortest path algoritm is applied
    * to the graph with the given source and destination nodes.
    * @return
    * An arrayList that contains the k-shortest paths.
    */

   public ArrayList<ArrayList<Integer>> getRoutingTable() {
       return routingTable;
   }
   
   /**
    * The method shows in the screen the number of path found to the 
    * given destination node.
    */

   public void getNumberOfPathsFound() {
       System.out.println("The number of paths found to the node " + i_destinationNode + " is: " + listKAlgorithm.size());
   }
  
   
   /**
    * Finds the KShortest Path using the Kshortest algorithm from JGrapthT
    * http://jgrapht.org/javadoc/org/jgrapht/alg/KShortestPaths.html It uses a
    * Bellman-Ford's variation
    * @param sourceNode
    * The source node of the multicast tree. It must be same in the tree.
    * @param destinationNode
    * The destination node in the set of destination nodes
    * @param numberOfPaths
    * The quantity of path the algorithm will find.
    */

   public void findKShortestPaths(int sourceNode, int destinationNode, int numberOfPaths) {
       i_sourceNode = sourceNode;
       i_destinationNode = destinationNode;
       i_numberOfPaths = numberOfPaths;
       //System.out.println(g.toString());
       kAlgorithm = new KShortestPaths<Long, DefaultEdge>(g, (long) i_sourceNode, i_numberOfPaths);
       listKAlgorithm = kAlgorithm.getPaths((long) i_destinationNode);
       populateRoutingTable();
   }

   
   /**
    * Method: populateRoutingTable
    * This method extract from the KShortest output the number of the nodes to build the
    * Routing table Example: 1 2 2 3 3 4 
    */
   private void populateRoutingTable() {
       routingTable = new ArrayList<ArrayList<Integer>>();
       String subPath;
       for (GraphPath<Long, DefaultEdge> pathString : listKAlgorithm) {
           routingTable.add(new ArrayList<Integer>());
           subPath = pathString.toString();
           StringTokenizer num = new StringTokenizer(subPath, ":(),[] ");
           while (num.hasMoreTokens()) {
               String digits = num.nextToken();
               routingTable.get(listKAlgorithm.indexOf(pathString)).add(Integer.parseInt(digits.trim()));
           }
// for (int i = 0; i < subPath.length(); i++) {
// char c = subPath.charAt(i);
// String stringCharacter = ""+c;
// if (Character.isDigit(c)) routingTable.get(listKAlgorithm.indexOf(pathString)).add(Integer.parseInt(stringCharacter)); 				
// }			
       }
       
       Collections.shuffle(routingTable, new Random());
   }
   
   /**
    * This a toString implementation to print in the screen
    * the routing table created by the class
    */

   public void printRoutingTable() {

       System.out.println("The routing table to the node " + i_destinationNode + " generated by the program: ");

       for (int i = 0; i < routingTable.size(); i++) {
           for (int j = 0; j < routingTable.get(i).size(); j++) {
               System.out.print(routingTable.get(i).get(j) + " ");
           }
           System.out.println();

       }
   }
   
   /**
    *This method is a toString implementation that shows the
    *output of the k-shortest path algorithm in JgraphT 
    */

   public void printKShortestPath() {
       System.out.println("KShortestPath to Node " + i_destinationNode + " = " + listKAlgorithm.toString());
   }
//instance variables
   private org.jgrapht.Graph g;
   private int i_sourceNode;
   private int i_destinationNode;
   private int i_numberOfPaths;
   private KShortestPaths<Long, DefaultEdge> kAlgorithm;
   private List<GraphPath<Long, DefaultEdge>> listKAlgorithm;
   private ArrayList<ArrayList<Integer>> routingTable;
}

